﻿#include "HTTPServer.h"

void NahidaProject::HTTPServer::AddRoute(const std::string& method, const std::string& path, Handler handler) {
	routes[method][path] = handler;
}

void NahidaProject::HTTPServer::ActionGet(const std::string& path, Handler handler) {
	AddRoute("GET", path, handler);
}

void NahidaProject::HTTPServer::ActionPost(const std::string& path, Handler handler) {
	AddRoute("POST", path, handler);
}

void NahidaProject::HTTPServer::ActionPut(const std::string& path, Handler handler) {
	AddRoute("PUT", path, handler);
}

void NahidaProject::HTTPServer::ActionDelete(const std::string& path, Handler handler) {
	AddRoute("DELETE", path, handler);
}

// 启动服务器
bool NahidaProject::HTTPServer::StartServer() {
	// 创建socket
	serverSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (serverSocket < 0) {
		std::cerr << "Failed to create socket" << std::endl;
		return false;
	}

	int opt = 1;
#ifdef _WIN32
	setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
#else
	setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#endif

	sockaddr_in serverAddress;
	memset(&serverAddress, 0, sizeof(serverAddress));
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_port = htons(port);
	serverAddress.sin_addr.s_addr = inet_addr(host.c_str());

	if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
		std::cerr << "Failed to bind socket" << std::endl;
		return false;
	}

	// 开始监听
	if (listen(serverSocket, 10) < 0) {
		std::cerr << "Failed to listen on socket" << std::endl;
		return false;
	}

	running = true;
	std::cout << "Server started on http://" << host << ":" << port << std::endl;

	// 主循环
	while (running) {
		sockaddr_in clientAddress;
		socklen_t clientLength = sizeof(clientAddress);

		int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientLength);
		if (clientSocket < 0) {
			if (running) {
				std::cerr << "Failed to accept connection" << std::endl;
			}
			continue;
		}

		// 为每个连接创建新线程处理
		std::thread([this, clientSocket]() {
			HandleClient(clientSocket);
			}).detach();
	}

	return true;
}

// 停止服务器
void NahidaProject::HTTPServer::StopServer() {
	running = false;
	if (serverSocket >= 0) {
#ifdef _WIN32
		closesocket(serverSocket);
#else
		close(serverSocket);
#endif
		serverSocket = -1;
	}
}

// 解析HTTP请求行
void NahidaProject::HTTPServer::ParseRequestLine(const std::string& line, HTTPRequest& request) {
	std::istringstream iss(line);
	iss >> request.method >> request.path >> request.version;

	// 解析查询参数
	size_t queryPosition = request.path.find('?');
	if (queryPosition != std::string::npos) {
		std::string queryString = request.path.substr(queryPosition + 1);
		request.path = request.path.substr(0, queryPosition);

		std::istringstream queryStream(queryString);
		std::string param;
		while (std::getline(queryStream, param, '&')) {
			size_t eq_pos = param.find('=');
			if (eq_pos != std::string::npos) {
				std::string key = param.substr(0, eq_pos);
				std::string value = param.substr(eq_pos + 1);
				request.queryParams[key] = value;
			}
		}
	}
}

// 解析HTTP头部
void NahidaProject::HTTPServer::ParseHeaders(std::istringstream& iss, HTTPRequest& request) {
	std::string line;
	while (std::getline(iss, line) && line != "\r") {
		size_t colonPosition = line.find(':');
		if (colonPosition != std::string::npos) {
			std::string key = line.substr(0, colonPosition);
			std::string value = line.substr(colonPosition + 1);

			// 去除前后空格
			key.erase(0, key.find_first_not_of(" \t\r\n"));
			key.erase(key.find_last_not_of(" \t\r\n") + 1);
			value.erase(0, value.find_first_not_of(" \t\r\n"));
			value.erase(value.find_last_not_of(" \t\r\n") + 1);

			request.headers[key] = value;
		}
	}
}

// 解析HTTP请求
bool NahidaProject::HTTPServer::ParseHTTPRequest(const std::string& raw_request, HTTPRequest& request) {
	std::istringstream iss(raw_request);
	std::string line;

	if (!std::getline(iss, line)) {
		return false;
	}

	ParseRequestLine(line, request);
	ParseHeaders(iss, request);

	std::ostringstream bodyStream;
	bodyStream << iss.rdbuf();
	request.body = bodyStream.str();

	return true;
}

// 构建HTTP响应
std::string NahidaProject::HTTPServer::BuildHTTPResponse(const HTTPResponse& response) {
	std::ostringstream oss;

	// 状态行
	oss << "HTTP/1.1 " << response.statusCode << " " << response.statusText << "\r\n";

	// 头部
	for (const auto& header : response.headers) {
		oss << header.first << ": " << header.second << "\r\n";
	}

	// 空行
	oss << "\r\n";

	// 响应体
	oss << response.body;

	return oss.str();
}

// 处理客户端连接
void NahidaProject::HTTPServer::HandleClient(int clientSocket) {
	try {
		// 接收数据
		char buffer[4096];
		std::string requestData;

		int bytes_received = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);
		if (bytes_received > 0) {
			buffer[bytes_received] = '\0';
			requestData = buffer;
		}

		if (!requestData.empty()) {
			HTTPRequest request;
			HTTPResponse response;

			// 解析请求
			if (ParseHTTPRequest(requestData, request)) {
				// 查找对应的处理器
				auto methodIt = routes.find(request.method);
				if (methodIt != routes.end()) {
					auto pathIt = methodIt->second.find(request.path);
					if (pathIt != methodIt->second.end()) {
						// 执行处理器
						pathIt->second(request, response);
					}
					else {
						// 404 Not Found
						response.statusCode = 404;
						response.statusText = "Not Found";
						response.body = "<h1>404 Not Found</h1>";
					}
				}
				else {
					// 405 Method Not Allowed
					response.statusCode = 405;
					response.statusText = "Method Not Allowed";
					response.body = "<h1>405 Method Not Allowed</h1>";
				}
			}
			else {
				// 400 Bad Request
				response.statusCode = 400;
				response.statusText = "Bad Request";
				response.body = "<h1>400 Bad Request</h1>";
			}

			// 发送响应
			std::string response_data = BuildHTTPResponse(response);
			send(clientSocket, response_data.c_str(), response_data.length(), 0);
		}
	}
	catch (const std::exception& e) {
		std::cerr << "Error handling client: " << e.what() << std::endl;
	}

	// 关闭连接
#ifdef _WIN32
	closesocket(clientSocket);
#else
	close(clientSocket);
#endif
}
